/*
 * Contexto.cpp
 *
 *  Created on: 11/06/2013
 *      Author: juan
 */

#include "Contexto.h"

Contexto::Contexto(string nuevoNombreDelContexto) {
	this->nombreDelContexto = nuevoNombreDelContexto;
	this->caracteresDelContexto = new list<Caracter*>;
	Caracter * caracterEscape = new Caracter(ESC);
	this->caracteresDelContexto->push_back(caracterEscape);
}


/*
 * Le pasa su contexto al compresor
 * y retorna el caracter que el compresor
 * les dio.
 */

Caracter *Contexto::descomprimiCaracter(Aritmetico *compresor) {
	Caracter* caracter = NULL;
	caracter = compresor->descomprimir_caracter(this->caracteresDelContexto);
	return caracter;
}

//Chequea si unCaracter es igual a algun caracter de los que se encuentran en la lista del contexto
bool Contexto::tenesCaracter(Caracter* unCaracter) {
	bool tieneCaracter = false;

	list<Caracter*>::iterator itCaracter = this->caracteresDelContexto->begin();

	while(itCaracter != this->caracteresDelContexto->end() && !tieneCaracter)
	{
		DatoContable * unDato = *itCaracter;
		if( *unDato==(DatoContable*)unCaracter )
		{
			tieneCaracter=true;
		}
		else
		{
			itCaracter++;
		}
	}

	return tieneCaracter;


}

//Pre:
//Pos1: El caracter no esta en la lista de caracter del contexto y se agrega un caracter nuevo con el mismo string con su contador en 1.
//Pos2: El caracter esta en la lista y se aumenta su contador
void Contexto::agregarCaracter(Caracter* unCaracter) {

	//Si el caracter es ESC y el tamaño de la lista es 1 no actualizo
	if (*unCaracter == "ESC" && caracteresDelContexto->size() == 1)
		return;

	if(this->tenesCaracter(unCaracter))
	{
		list<Caracter*>::iterator itCaracter = this->caracteresDelContexto->begin();
		DatoContable * unDato = *itCaracter;

		while( (*unDato==(DatoContable*)unCaracter ) == false)
		{
			itCaracter++;
			unDato = *itCaracter;
		}

		(*itCaracter)->aumentarContador();
	}
	else
	{
		string nuevoDatoCaracter;
		unCaracter->getDato(nuevoDatoCaracter);
		Caracter * nuevoCaracter = new Caracter(nuevoDatoCaracter);
		nuevoCaracter->setContador(1);
		this->caracteresDelContexto->push_back(nuevoCaracter);
	}
}


//Pre:
//Pos1: Retorno -1 | El caracter no esta en la lista de caracter del contexto y se lo agrega con su contador en 1.
//Pos2: Retorno 0  | El caracter esta en la lista y se aumenta su contador
int Contexto::comprimirCaracter(Caracter* unCaracter, Aritmetico* unAritmetico) {

	if(this->tenesCaracter(unCaracter))
	{
		list<Caracter*>::iterator itCaracter = this->caracteresDelContexto->begin();
		DatoContable * unDato = *itCaracter;

		while( (*unDato==(DatoContable*)unCaracter ) == false)
		{
			itCaracter++;
			unDato = *itCaracter;
		}
		unAritmetico->comprimir(this->caracteresDelContexto, unCaracter);
		(*itCaracter)->aumentarContador();
		delete unCaracter;
		return 0;
	}
	else	{

		unAritmetico->comprimir(this->caracteresDelContexto, this->escape());
		if (this->caracteresDelContexto->size() > 1) {
			this->escape()->aumentarContador();
		}
		unCaracter->setContador(1);
		this->caracteresDelContexto->push_back(unCaracter);
		return -1;
	}
}

Caracter* Contexto::escape() {

	list<Caracter*>::iterator itCaracter = this->caracteresDelContexto->begin();
	DatoContable * unDato = *itCaracter;

	while( (*unDato==(string)ESC ) == false)
	{
		itCaracter++;
		unDato = *itCaracter;
	}


	return *itCaracter;


}



Contexto::~Contexto() {
	list<Caracter*>::iterator itLista = this->caracteresDelContexto->begin();

	while(itLista != this->caracteresDelContexto->end())
	{
		Caracter* unCaracter = *itLista;
		delete unCaracter;
		itLista++;
	}

	delete this->caracteresDelContexto;

}

